﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using PaperRenderingInterfaces;
using DeepZoomPivotConstructor.PivotLib;
using HtmlAgilityPack;
using PaperPluginUtilities;
using DeepZoomPivotConstructor.ErrorAndLoggingInterfaces;

namespace TwikiLinkScanners
{
    /// <summary>
    /// Scan a twiki page for links to other twiki pages, and then run them
    /// with the specified sub-dude.
    /// 
    /// /ScannerType=blah/http://address
    /// 
    /// Where
    /// 
    ///   ScannerType=x - x is what the sub-scanner will be run.
    /// 
    /// </summary>
    [Export(typeof(IPaperRender))]
    [PaperRender("TwikSubLinkScanner")]
    public class ATLASSubLinkedTwikiPages : IPaperRender
    {
#pragma warning disable 0649
        [Import]
        IWebAccess WebGetter;
#pragma warning restore 0649

#pragma warning disable 0649
        [Import]
        IPaperRenderEngine MyRender;
#pragma warning restore 0649

#pragma warning disable 0649
        [Import(AllowDefault = true)]
        IErrorLogger MyLogger;
#pragma warning restore 0649

        public IEnumerable<PivotImage> Render(string renderAddress)
        {
            ///
            /// Parse the parameters
            /// 

            var parms = ParseConfigString(renderAddress);
            if (!parms.ContainsKey("url") || parms["url"].Length == 0)
            {
                throw new ArgumentException("Missing url");
            }
            if (!parms.ContainsKey("ScannerType") || parms["ScannerType"].Length == 0)
            {
                throw new ArgumentException("Missing ScannerType argument");
            }

            ///
            /// Load up the html now
            /// 

            HtmlDocument doc = new HtmlDocument();
            Uri baseUri = new Uri(parms["url"]);
            doc.LoadHtml(WebGetter.GetUriAsString(baseUri));

            ///
            /// Next, make sure this is a real twiki page. If not, then we are outta here!
            /// 

            if (!TwikiParseHelpers.isATLASPublicResultsPage(doc.DocumentNode))
            {
                if (MyLogger != null)
                {
                    MyLogger.LogMessage("ATALSSubLinkTwikiPages", "Twiki page requested is not part of the public ATLAS web: " + parms["url"]);
                }
                return Enumerable.Empty<PivotImage>();
            }

            ///
            /// Look for all twiki guys that point outwards
            /// 

            var allLinks = new EnumerableWrapper<HtmlNode>(doc.DocumentNode.SelectNodes("//a[@href]"));
            var twikiSubLinks = (from l in allLinks
                                where l.InnerText.Length > 0
                                let href = l.Attributes["href"].Value
                                let u = new Uri(baseUri, href)
                                where TwikiParseHelpers.isATLASTwikiLink(u)
                                let twikiWord = TwikiParseHelpers.ExtractATLASTwikiWord(u)
                                where TwikiParseHelpers.IsSingleTwikiWord(twikiWord) && !TwikiParseHelpers.MainATLASTwikiWord(twikiWord)
                                select u).ToArray();

            var allRendered = twikiSubLinks.SelectMany(l => MyRender.Render(parms["ScannerType"], l.OriginalString));
            var allSubRendered = twikiSubLinks.SelectMany(l => MyRender.Render("TwikSubLinkScanner", "/ScannerType=" + parms["ScannerType"] + "/" + l.OriginalString));
            return allRendered.Concat(allSubRendered);
        }

        /// <summary>
        /// We parse the string for the information required.
        /// The format is /xxx/http:// where xxx is a comma seperated list of name=value pairs.
        /// </summary>
        /// <param name="renderAddress"></param>
        /// <returns></returns>
        private Dictionary<string, string> ParseConfigString(string renderAddress)
        {
            if (renderAddress == null || renderAddress.Length == 0)
            {
                throw new ArgumentException("Can not be null or empty string!", "renderAddress");
            }

            ///
            /// Create the basics of what we are going to be returning for parameters, and
            /// also fill in default settings.
            /// 

            Dictionary<string, string> result = new Dictionary<string, string>();
            result["PlotPageScanner"] = "HTMLSimpleTableCells";

            ///
            /// Split off the URL and the settings stuff. If there are no settings we take
            /// defaults above.
            /// 

            if (renderAddress[0] != '/')
            {
                result["url"] = renderAddress;
                return result;
            }

            string parameters = renderAddress.Substring(1);
            int closeingSlash = parameters.IndexOf("/");
            result["url"] = parameters.Substring(closeingSlash + 1);
            parameters = parameters.Substring(0, closeingSlash);

            var nameValue = from p in parameters.Split(',')
                            let nv = p.Split(new char[] { '=' }, 2)
                            select nv;
            foreach (var item in nameValue)
            {
                if (item.Length == 2)
                {
                    result[item[0]] = item[1];
                } if (item.Length == 1)
                {
                    result["url"] = item[0];
                }
            }
            return result;
        }
    }
}
